#include "stdafx.h"
#include <cassert>

#include "FakeDirect3D9.h"

using namespace rt::Fakes;

FakeDirect3D9::FakeDirect3D9()
	: FakeUnknown(),
	RegisterSoftwareDeviceCalled(false),
	RegisterSoftwareDeviceLastInitializeFunction(0),
	RegisterSoftwareDeviceFakeHResult(E_FAIL),
	GetAdapterCountCalled(false),
	GetAdapterCountFakeResult(0U),
	GetAdapterIdentifierCalled(false),
	GetAdapterIdentifierLastAdapter(),
	GetAdapterIdentifierLastFlags(),
	GetAdapterIdentifierFakeResult(),
	GetAdapterIdentifierFakeHResult(),
	GetAdapterModeCountCalled(false),
	GetAdapterModeCountLastAdapter(),
	GetAdapterModeCountLastFormat(),
	GetAdapterModeCountFakeResult(),
	EnumAdapterModesCalled(false),
	EnumAdapterModesLastAdapter(),
	EnumAdapterModesLastFormat(),
	EnumAdapterModesLastMode(),
	EnumAdapterModesFakeResult(),
	EnumAdapterModesFakeHResult(),
	GetAdapterDisplayModeCalled(false),
	GetAdapterDisplayModeLastAdapter(),
	GetAdapterDisplayModeFakeResult(),
	GetAdapterDisplayModeFakeHResult(),
	CheckDeviceTypeCalled(false),
	CheckDeviceTypeLastAdapter(),
	CheckDeviceTypeLastDevType(),
	CheckDeviceTypeLastAdapterFormat(),
	CheckDeviceTypeLastBackBufferFormat(),
	CheckDeviceTypeLastWindowed(),
	CheckDeviceTypeFakeHResult(),
	CheckDeviceFormatCalled(false),
	CheckDeviceFormatLastAdapter(),
	CheckDeviceFormatLastDeviceType(),
	CheckDeviceFormatLastAdapterFormat(),
	CheckDeviceFormatLastUsage(),
	CheckDeviceFormatLastRType(),
	CheckDeviceFormatLastCheckFormat(),
	CheckDeviceFormatFakeHResult(),
	CheckDeviceMultiSampleTypeCalled(false),
	CheckDeviceMultiSampleTypeLastAdapter(),
	CheckDeviceMultiSampleTypeLastDeviceType(),
	CheckDeviceMultiSampleTypeLastSurfaceFormat(),
	CheckDeviceMultiSampleTypeLastWindowed(),
	CheckDeviceMultiSampleTypeLastMultiSampleType(),
	CheckDeviceMultiSampleTypeFakeQualityLevels(),
	CheckDeviceMultiSampleTypeFakeHResult(),
	CheckDepthStencilMatchCalled(false),
	CheckDepthStencilMatchLastAdapter(),
	CheckDepthStencilMatchLastDeviceType(),
	CheckDepthStencilMatchLastAdapterFormat(),
	CheckDepthStencilMatchLastRenderTargetFormat(),
	CheckDepthStencilMatchLastDepthStencilFormat(),
	CheckDepthStencilMatchFakeHResult(),
	CheckDeviceFormatConversionCalled(false),
	CheckDeviceFormatConversionLastAdapter(),
	CheckDeviceFormatConversionLastDeviceType(),
	CheckDeviceFormatConversionLastSourceFormat(),
	CheckDeviceFormatConversionLastTargetFormat(),
	CheckDeviceFormatConversionFakeHResult(),
	GetDeviceCapsCalled(false),
	GetDeviceCapsLastAdapter(),
	GetDeviceCapsLastDeviceType(),
	GetDeviceCapsFakeResult(),
	GetDeviceCapsFakeHResult(),
	GetAdapterMonitorCalled(false),
	GetAdapterMonitorLastAdapter(),
	GetAdapterMonitorFakeResult(),
	CreateDeviceCalled(false),
	CreateDeviceLastAdapter(),
	CreateDeviceLastDeviceType(),
	CreateDeviceLastFocusWindow(),
	CreateDeviceLastBehaviorFlags(),
	CreateDeviceLastPresentationParameters(),
	CreateDeviceFakeDeviceInterface(),
	CreateDeviceFakeHResult()
{
}

FakeDirect3D9::~FakeDirect3D9()
{
}

/*** IDirect3D9 methods ***/
HRESULT FakeDirect3D9::RegisterSoftwareDevice(void *pInitializeFunction)
{
	RegisterSoftwareDeviceCalled = true;
	RegisterSoftwareDeviceLastInitializeFunction = pInitializeFunction;
	return RegisterSoftwareDeviceFakeHResult;
}
UINT FakeDirect3D9::GetAdapterCount()
{
	GetAdapterCountCalled = true;
	return GetAdapterCountFakeResult;
}
HRESULT FakeDirect3D9::GetAdapterIdentifier(UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER9* pIdentifier)
{
	GetAdapterIdentifierCalled = true;
	GetAdapterIdentifierLastAdapter.push_back(Adapter);
	GetAdapterIdentifierLastFlags.push_back(Flags);
	assert(pIdentifier);
	*pIdentifier = GetAdapterIdentifierFakeResult[Adapter];
	return GetAdapterIdentifierFakeHResult[Adapter];
}
UINT FakeDirect3D9::GetAdapterModeCount(UINT Adapter,D3DFORMAT Format)
{
	GetAdapterModeCountCalled = true;
	GetAdapterModeCountLastAdapter.push_back(Adapter);
	GetAdapterModeCountLastFormat.push_back(Format);
	return GetAdapterModeCountFakeResult[Adapter];
}
HRESULT FakeDirect3D9::EnumAdapterModes(UINT Adapter,D3DFORMAT Format,UINT Mode,D3DDISPLAYMODE* pMode)
{
	EnumAdapterModesCalled = true;
	EnumAdapterModesLastAdapter.push_back(Adapter);
	EnumAdapterModesLastFormat.push_back(Format);
	EnumAdapterModesLastMode.push_back(Mode);
	assert(pMode);
	EnumAdapterModesFakeResultKey key = { Adapter, Format, Mode };
	*pMode = EnumAdapterModesFakeResult[key];
	return EnumAdapterModesFakeHResult[key];
}
HRESULT FakeDirect3D9::GetAdapterDisplayMode(UINT Adapter,D3DDISPLAYMODE* pMode)
{
	GetAdapterDisplayModeCalled = true;
	GetAdapterDisplayModeLastAdapter.push_back(Adapter);
	assert(pMode);
	*pMode = GetAdapterDisplayModeFakeResult[Adapter];
	return GetAdapterDisplayModeFakeHResult[Adapter];
}
HRESULT FakeDirect3D9::CheckDeviceType(UINT Adapter,
									   D3DDEVTYPE DevType,
									   D3DFORMAT AdapterFormat,
									   D3DFORMAT BackBufferFormat,
									   BOOL bWindowed)
{
	CheckDeviceTypeCalled = true;
	CheckDeviceTypeLastAdapter.push_back(Adapter);
	CheckDeviceTypeLastDevType.push_back(DevType);
	CheckDeviceTypeLastAdapterFormat.push_back(AdapterFormat);
	CheckDeviceTypeLastBackBufferFormat.push_back(BackBufferFormat);
	CheckDeviceTypeLastWindowed.push_back(bWindowed);
	return CheckDeviceTypeFakeHResult[Adapter];
}
HRESULT FakeDirect3D9::CheckDeviceFormat(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,
										 DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat)
{
	CheckDeviceFormatCalled = true;
	CheckDeviceFormatLastAdapter.push_back(Adapter);
	CheckDeviceFormatLastDeviceType.push_back(DeviceType);
	CheckDeviceFormatLastAdapterFormat.push_back(AdapterFormat);
	CheckDeviceFormatLastUsage.push_back(Usage);
	CheckDeviceFormatLastRType.push_back(RType);
	CheckDeviceFormatLastCheckFormat.push_back(CheckFormat);
	return CheckDeviceFormatFakeHResult[Adapter];
}
HRESULT FakeDirect3D9::CheckDeviceMultiSampleType(UINT Adapter,D3DDEVTYPE DeviceType,
												  D3DFORMAT SurfaceFormat,BOOL Windowed,
												  D3DMULTISAMPLE_TYPE MultiSampleType,
												  DWORD* pQualityLevels)
{
	CheckDeviceMultiSampleTypeCalled = true;
	CheckDeviceMultiSampleTypeLastAdapter.push_back(Adapter);
	CheckDeviceMultiSampleTypeLastDeviceType.push_back(DeviceType);
	CheckDeviceMultiSampleTypeLastSurfaceFormat.push_back(SurfaceFormat);
	CheckDeviceMultiSampleTypeLastWindowed.push_back(Windowed);
	CheckDeviceMultiSampleTypeLastMultiSampleType.push_back(MultiSampleType);
	assert(pQualityLevels);
	*pQualityLevels = CheckDeviceMultiSampleTypeFakeQualityLevels[Adapter];
	return CheckDeviceMultiSampleTypeFakeHResult[Adapter];
}
HRESULT FakeDirect3D9::CheckDepthStencilMatch(UINT Adapter,
											  D3DDEVTYPE DeviceType,
											  D3DFORMAT AdapterFormat,
											  D3DFORMAT RenderTargetFormat,
											  D3DFORMAT DepthStencilFormat)
{
	CheckDepthStencilMatchCalled = true;
	CheckDepthStencilMatchLastAdapter.push_back(Adapter);
	CheckDepthStencilMatchLastDeviceType.push_back(DeviceType);
	CheckDepthStencilMatchLastAdapterFormat.push_back(AdapterFormat);
	CheckDepthStencilMatchLastRenderTargetFormat.push_back(RenderTargetFormat);
	CheckDepthStencilMatchLastDepthStencilFormat.push_back(DepthStencilFormat);
	return CheckDepthStencilMatchFakeHResult[Adapter];
}
HRESULT FakeDirect3D9::CheckDeviceFormatConversion(UINT Adapter,
												   D3DDEVTYPE DeviceType,
												   D3DFORMAT SourceFormat,
												   D3DFORMAT TargetFormat)
{
	CheckDeviceFormatConversionCalled = true;
	CheckDeviceFormatConversionLastAdapter.push_back(Adapter);
	CheckDeviceFormatConversionLastDeviceType.push_back(DeviceType);
	CheckDeviceFormatConversionLastSourceFormat.push_back(SourceFormat);
	CheckDeviceFormatConversionLastTargetFormat.push_back(TargetFormat);
	return CheckDeviceFormatConversionFakeHResult[Adapter];
}
HRESULT FakeDirect3D9::GetDeviceCaps(UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS9* pCaps)
{
	GetDeviceCapsCalled = true;
	GetDeviceCapsLastAdapter.push_back(Adapter);
	GetDeviceCapsLastDeviceType.push_back(DeviceType);
	assert(pCaps);
	*pCaps = GetDeviceCapsFakeResult[Adapter];
	return GetDeviceCapsFakeHResult[Adapter];
}
HMONITOR FakeDirect3D9::GetAdapterMonitor(UINT Adapter)
{
	GetAdapterMonitorCalled = true;
	GetAdapterMonitorLastAdapter.push_back(Adapter);
	return GetAdapterMonitorFakeResult[Adapter];
}
HRESULT FakeDirect3D9::CreateDevice(UINT Adapter,
									D3DDEVTYPE DeviceType,
									HWND hFocusWindow,
									DWORD BehaviorFlags,
									D3DPRESENT_PARAMETERS* pPresentationParameters,
									IDirect3DDevice9** ppReturnedDeviceInterface)
{
	CreateDeviceCalled = true;
	CreateDeviceLastAdapter.push_back(Adapter);
	CreateDeviceLastDeviceType.push_back(DeviceType);
	CreateDeviceLastFocusWindow.push_back(hFocusWindow);
	CreateDeviceLastBehaviorFlags.push_back(BehaviorFlags);
	assert(pPresentationParameters);
	CreateDeviceLastPresentationParameters.push_back(*pPresentationParameters);
	assert(ppReturnedDeviceInterface);
	*ppReturnedDeviceInterface = CreateDeviceFakeDeviceInterface[Adapter];
	return CreateDeviceFakeHResult[Adapter];
}

